package com.ermax.aircond.manage.web.bean;

import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedProperty;
import javax.faces.context.FacesContext;
import javax.faces.event.ValueChangeEvent;
import javax.faces.model.SelectItem;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.annotation.Scope;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;

import com.ermax.aircond.common.parameter.Status;
import com.ermax.aircond.maintain.domain.Building;
import com.ermax.aircond.maintain.domain.Floor;
import com.ermax.aircond.maintain.domain.Machine;
import com.ermax.aircond.maintain.domain.Room;
import com.ermax.aircond.maintain.service.MaintainService;
import com.ermax.aircond.manage.domain.ScheduleTerm;
import com.ermax.aircond.manage.service.ScheduleControlService;
import com.ermax.aircond.resource.MessageBundle;
import com.ermax.aircond.util.web.bean.DataTableBean;

@Scope("view")
@Component
public class MassScheduleManageBean extends DataTableBean implements java.io.Serializable {

	private static final long serialVersionUID = 1L;
	private static final Logger logger = LoggerFactory.getLogger(MassScheduleManageBean.class);
	private static final String STATUS_INIT = "INIT";
	private static final String STATUS_SELECT = "SELECT";
	private static final String STATUS_CONTROL = "CONTROL";
	

	@Resource(name = "maintainService")
	private MaintainService maintainService;
	@Resource(name = "scheduleControlService")
	private ScheduleControlService scheduleControlService;

	@ManagedProperty(value = "#{loginBean.sessionUser}")
	private String sessionUser;

	private List<SelectItem> buildingOptions = new ArrayList<SelectItem>();
	private List<SelectItem> floorOptions = new ArrayList<SelectItem>();
	private List<SelectItem> roomOptions = new ArrayList<SelectItem>();
	private List<SelectItem> machineOptions = new ArrayList<SelectItem>();
	private List<SelectItem> minimumTemperatureOptions = new ArrayList<SelectItem>();
	private List<SelectItem> temperatureOptions = new ArrayList<SelectItem>();
	
	private long selectedBuildingId;
	private long selectedFloorId;
	private long selectedRoomId;
	private long selectedMachineId;

	private List<String> clickedMachineId = new ArrayList<String>();
	private List<SelectItem> clickedMachineOptions = new ArrayList<SelectItem>();
	private List<Machine> selectedMachines = new ArrayList<Machine>();

	private List<ScheduleTerm> scheduleTerms = new ArrayList<ScheduleTerm>();
	private ScheduleTerm editItem = new ScheduleTerm();
	
	private List<SelectItem> hourOptions = new ArrayList<SelectItem>();
	private List<SelectItem> minuteOptions = new ArrayList<SelectItem>();

	private String status = "";
	
	@PostConstruct
	public void init() {
		try {
			reset();
		} catch (Exception ex) {
			String message = MessageBundle.getInstance().getMessage("error_init_fail", FacesContext.getCurrentInstance().getViewRoot().getLocale());
			FacesMessage facesMessage = new FacesMessage(message);
			FacesContext.getCurrentInstance().addMessage(null, facesMessage);
		}
	}

	private void reset() throws Exception {
		hourOptions = createHourOptions();
		minuteOptions = createMinuteOptions();
		buildingOptions = createBuildingOptions();
		floorOptions = createFloorOptions();
		roomOptions = createRooomOptions();
		machineOptions = createMachineOptions();
		temperatureOptions = createTemperatureOptions();
		minimumTemperatureOptions = createMinimumTemperatureOptions();
		scheduleTerms.clear();
		clickedMachineId.clear();
		clickedMachineOptions.clear();
		setEditItem(new ScheduleTerm());
		status = STATUS_INIT;
		selectedMachines.clear();
	}

	
	public void search(){		
		clickedMachineId.clear();
		clickedMachineOptions.clear();
		status = STATUS_SELECT;
		
		// search by machine
		if (selectedMachineId > 0) {
			try {
				Machine machine = maintainService.getMachineById(selectedMachineId);				
				StringBuilder sb = new StringBuilder();
				sb.append(machine.getRoom().getFloor().getBuilding().getBuildingName());
				sb.append(", ");
				sb.append(machine.getRoom().getFloor().getFloorName());
				sb.append(", ");
				sb.append(machine.getRoom().getRoomName());
				sb.append(", ");
				sb.append(machine.getMachineName());
				
				SelectItem selectItem = new SelectItem(machine.getMachineId(), sb.toString());
				clickedMachineOptions.add(selectItem);
			} catch (Exception e) {
				logger.error(e.getLocalizedMessage());
			}
			return;
		}

		// search by room
		if (selectedRoomId > 0) {
			try {
				Room room = maintainService.getRoomById(selectedRoomId);
				List<Machine> machines = maintainService.getMachines(null, null, room, null, Status.ACTIVE);
				Iterator<Machine> iterator = machines.iterator();
				while (iterator.hasNext()) {
					Machine machine = iterator.next();
					StringBuilder sb = new StringBuilder();
					sb.append(machine.getRoom().getFloor().getBuilding().getBuildingName());
					sb.append(", ");
					sb.append(machine.getRoom().getFloor().getFloorName());
					sb.append(", ");
					sb.append(machine.getRoom().getRoomName());
					sb.append(", ");
					sb.append(machine.getMachineName());
					
					SelectItem selectItem = new SelectItem(machine.getMachineId(), sb.toString());
					clickedMachineOptions.add(selectItem);
				}
			} catch (Exception e) {
				logger.error(e.getLocalizedMessage());
			}
			return;
		}

		// search by floor
		if (selectedFloorId > 0) {
			try {
				Floor floor = maintainService.getFloorById(selectedFloorId);
				List<Machine> machines = maintainService.getMachines(null, floor, null, null, Status.ACTIVE);
				Iterator<Machine> iterator = machines.iterator();
				while (iterator.hasNext()) {
					Machine machine = iterator.next();
					StringBuilder sb = new StringBuilder();
					sb.append(machine.getRoom().getFloor().getBuilding().getBuildingName());
					sb.append(", ");
					sb.append(machine.getRoom().getFloor().getFloorName());
					sb.append(", ");
					sb.append(machine.getRoom().getRoomName());
					sb.append(", ");
					sb.append(machine.getMachineName());
					
					SelectItem selectItem = new SelectItem(machine.getMachineId(), sb.toString());
					clickedMachineOptions.add(selectItem);
				}
			} catch (Exception e) {
				logger.error(e.getLocalizedMessage());
			}
			return;
		}

		// search by building
		if (selectedBuildingId > 0) {
			try {
				Building building = maintainService.getBuildingById(selectedBuildingId);
				List<Machine> machines = maintainService.getMachines(building, null, null, null, Status.ACTIVE);
				Iterator<Machine> iterator = machines.iterator();
				while (iterator.hasNext()) {
					Machine machine = iterator.next();
					StringBuilder sb = new StringBuilder();
					sb.append(machine.getRoom().getFloor().getBuilding().getBuildingName());
					sb.append(", ");
					sb.append(machine.getRoom().getFloor().getFloorName());
					sb.append(", ");
					sb.append(machine.getRoom().getRoomName());
					sb.append(", ");
					sb.append(machine.getMachineName());
					
					SelectItem selectItem = new SelectItem(machine.getMachineId(), sb.toString());
					clickedMachineOptions.add(selectItem);
				}
			} catch (Exception e) {
				logger.error(e.getLocalizedMessage());
			}
			return;
		}
	}
	
	public void view(){
		scheduleTerms.clear();
		selectedMachines.clear();
		status = STATUS_CONTROL;
		try{
			Iterator<String> iterator = clickedMachineId.iterator();
			while(iterator.hasNext()){
				long id = Long.valueOf(iterator.next());
				Machine machine = maintainService.getMachineById(id);
				selectedMachines.add(machine);
				scheduleTerms.addAll(scheduleControlService.getScheduleTerm(machine));
			}
		}catch (Exception e) {
			logger.error(e.getLocalizedMessage());
		}
	}
	
	public void selectAll(){
		clickedMachineId.clear();
		Iterator<SelectItem> iterator = clickedMachineOptions.iterator();
		while(iterator.hasNext()){
			SelectItem selectItem = iterator.next();
			clickedMachineId.add(String.valueOf(selectItem.getValue()));
		}
	}
	
	public void clear(){
		clickedMachineId.clear();
	}

	public void apply() {
		try {
			Date date = new Date();
			UserDetails userDetails=  (UserDetails) SecurityContextHolder.getContext().getAuthentication().getPrincipal();

			Iterator<Machine> iterator = selectedMachines.iterator();
			while(iterator.hasNext()){
				Machine machine = iterator.next();
				ScheduleTerm scheduleTerm = new ScheduleTerm();
				scheduleTerm.setCreateDate(date);
				scheduleTerm.setCreateUser(userDetails.getUsername());
				scheduleTerm.setUpdateDate(date);
				scheduleTerm.setUpdateUser(userDetails.getUsername());
				
				scheduleTerm.setMachine(machine);
				
				scheduleTerm.setActive(editItem.isActive());
				scheduleTerm.setControlMode(editItem.getControlMode());
				scheduleTerm.setCmd(editItem.getCmd());
				scheduleTerm.setFanSpeed(editItem.getFanSpeed());
				scheduleTerm.setMinimumTemperature(editItem.getMinimumTemperature());
				scheduleTerm.setNid(editItem.getNid());
				scheduleTerm.setScheduleHour(editItem.getScheduleHour());
				scheduleTerm.setScheduleMin(editItem.getScheduleMin());
				scheduleTerm.setStart(editItem.isStart());
				scheduleTerm.setTemperature(editItem.getTemperature());
				scheduleTerm.setUnmonitored(editItem.getUnmonitored());
				scheduleTerm.setWindValue(editItem.getWindValue());
				scheduleTerm.setKeyLock(editItem.getKeyLock());
				scheduleTerm.setErrorMessage(editItem.getErrorMessage());
				
				
				scheduleTerm.setExecMon(editItem.isExecMon());
				scheduleTerm.setExecTue(editItem.isExecTue());
				scheduleTerm.setExecWed(editItem.isExecWed());
				scheduleTerm.setExecThu(editItem.isExecThu());
				scheduleTerm.setExecFri(editItem.isExecFri());
				scheduleTerm.setExecSat(editItem.isExecSat());
				scheduleTerm.setExecSun(editItem.isExecSun());
				
				scheduleControlService.createSchedule(scheduleTerm);
			}
			init();
			String message = MessageBundle.getInstance().getMessage("info_apply_success", FacesContext.getCurrentInstance().getViewRoot().getLocale());
			FacesMessage facesMessage = new FacesMessage(message);
			FacesContext.getCurrentInstance().addMessage(null, facesMessage);
		} catch (Exception ex) {
			String message = MessageBundle.getInstance().getMessage("error_create_fail", FacesContext.getCurrentInstance().getViewRoot().getLocale());
			FacesMessage facesMessage = new FacesMessage(message);
			FacesContext.getCurrentInstance().addMessage(null, facesMessage);
		}
	}

	public void buildingValueChanged(ValueChangeEvent event) {
		if (null != event.getNewValue()) {
			selectedFloorId = 0;
			selectedRoomId = 0;
			selectedMachineId = 0;
			selectedBuildingId = (Long) event.getNewValue();
			floorOptions = createFloorOptions();
			roomOptions = createRooomOptions();
			machineOptions = createMachineOptions();
		}
	}

	public void floorValueChanged(ValueChangeEvent event) {
		if (null != event.getNewValue()) {
			selectedRoomId = 0;
			selectedMachineId = 0;
			selectedFloorId = (Long) event.getNewValue();
			roomOptions = createRooomOptions();
			machineOptions = createMachineOptions();
		}
	}

	public void roomValueChanged(ValueChangeEvent event) {
		if (null != event.getNewValue()) {
			selectedMachineId = 0;
			selectedRoomId = (Long) event.getNewValue();
			machineOptions = createMachineOptions();
		}
	}

	private List<SelectItem> createBuildingOptions() {
		List<SelectItem> results = new ArrayList<SelectItem>();
		results.add(new SelectItem(0,"------"));
		try {
			List<Building> buildings = maintainService.getAllBuildings(Status.ACTIVE);
			for (Building building : buildings) {
				SelectItem item = new SelectItem(building.getBuildingId(), building.getBuildingName());
				results.add(item);
			}
		} catch (Exception e) {
			logger.error(e.getMessage());
		}

		return results;
	}

	private List<SelectItem> createFloorOptions() {
		List<SelectItem> results = new ArrayList<SelectItem>();
		results.add(new SelectItem(0,"------"));
		try {
			if (selectedBuildingId > 0) {
				Building selectedBuilding = maintainService.getBuildingById(selectedBuildingId);
				List<Floor> floors = maintainService.getFloors(selectedBuilding, null, Status.ACTIVE);
				for (Floor floor : floors) {
					SelectItem item = new SelectItem(floor.getFloorId(), floor.getFloorName());
					results.add(item);
				}
			}
		} catch (Exception e) {
			logger.error(e.getMessage());
		}
		return results;
	}

	private List<SelectItem> createRooomOptions() {
		List<SelectItem> results = new ArrayList<SelectItem>();
		results.add(new SelectItem(0,"------"));
		try {
			if (selectedFloorId > 0) {
				Floor selectedFloor = maintainService.getFloorById(selectedFloorId);
				List<Room> rooms = maintainService.getRooms(null, selectedFloor, null, Status.ACTIVE);
				for (Room room : rooms) {
					SelectItem item = new SelectItem(room.getRoomId(), room.getRoomName());
					results.add(item);
				}
			}
		} catch (Exception e) {
			logger.error(e.getLocalizedMessage());
		}
		return results;
	}

	private List<SelectItem> createMachineOptions() {
		List<SelectItem> results = new ArrayList<SelectItem>();
		results.add(new SelectItem(0,"------"));
		try {
			if (selectedRoomId > 0) {
				Room selectedRoom = maintainService.getRoomById(selectedRoomId);
				List<Machine> machines = maintainService.getMachines(null, null, selectedRoom, null, Status.ACTIVE);
				for (Machine machine : machines) {
					SelectItem item = new SelectItem(machine.getMachineId(), machine.getMachineName());
					results.add(item);
				}
			}
		} catch (Exception e) {
			logger.error(e.getLocalizedMessage());
		}
		return results;
	}
	
	private List<SelectItem> createHourOptions(){
		List<SelectItem> results = new ArrayList<SelectItem>();
		results.add(new SelectItem("00", "00"));
		results.add(new SelectItem("01", "01"));
		results.add(new SelectItem("02", "02"));
		results.add(new SelectItem("03", "03"));
		results.add(new SelectItem("04", "04"));
		results.add(new SelectItem("05", "05"));
		results.add(new SelectItem("06", "06"));
		results.add(new SelectItem("07", "07"));
		results.add(new SelectItem("08", "08"));
		results.add(new SelectItem("09", "09"));
		results.add(new SelectItem("10", "10"));
		results.add(new SelectItem("11", "11"));
		results.add(new SelectItem("12", "12"));
		results.add(new SelectItem("13", "13"));
		results.add(new SelectItem("14", "14"));
		results.add(new SelectItem("15", "15"));
		results.add(new SelectItem("16", "16"));
		results.add(new SelectItem("17", "17"));
		results.add(new SelectItem("18", "18"));
		results.add(new SelectItem("19", "19"));
		results.add(new SelectItem("20", "20"));
		results.add(new SelectItem("21", "21"));
		results.add(new SelectItem("22", "22"));
		results.add(new SelectItem("23", "23"));
		return results;	
	}
	
	private List<SelectItem> createMinuteOptions(){
		List<SelectItem> results = new ArrayList<SelectItem>();
		results.add(new SelectItem("00", "00"));
		results.add(new SelectItem("05", "05"));
		results.add(new SelectItem("10", "10"));
		results.add(new SelectItem("15", "15"));
		results.add(new SelectItem("20", "20"));
		results.add(new SelectItem("25", "25"));
		results.add(new SelectItem("30", "30"));
		results.add(new SelectItem("35", "35"));
		results.add(new SelectItem("40", "40"));
		results.add(new SelectItem("45", "45"));
		results.add(new SelectItem("50", "50"));
		results.add(new SelectItem("55", "55"));			
		return results;
	}
	
	private List<SelectItem> createTemperatureOptions(){
		List<SelectItem> results = new ArrayList<SelectItem>();
		for(int i=16; i<=32; i++){
			results.add(new SelectItem(i,String.valueOf(i)));
		}
		return results;
	}
	
	private List<SelectItem> createMinimumTemperatureOptions(){
		List<SelectItem> results = new ArrayList<SelectItem>();
		results.add(new SelectItem(0,String.valueOf(0)));
		for(int i=16; i<=32; i++){
			results.add(new SelectItem(i,String.valueOf(i)));
		}
		
		return results;
	}

	public MaintainService getMaintainService() {
		return maintainService;
	}

	public void setMaintainService(MaintainService maintainService) {
		this.maintainService = maintainService;
	}

	public List<SelectItem> getBuildingOptions() {
		return buildingOptions;
	}

	public void setBuildingOptions(List<SelectItem> buildingOptions) {
		this.buildingOptions = buildingOptions;
	}

	public List<SelectItem> getFloorOptions() {
		return floorOptions;
	}

	public void setFloorOptions(List<SelectItem> floorOptions) {
		this.floorOptions = floorOptions;
	}

	public List<SelectItem> getRoomOptions() {
		return roomOptions;
	}

	public void setRoomOptions(List<SelectItem> roomOptions) {
		this.roomOptions = roomOptions;
	}

	public List<SelectItem> getMachineOptions() {
		return machineOptions;
	}

	public void setMachineOptions(List<SelectItem> machineOptions) {
		this.machineOptions = machineOptions;
	}

	public long getSelectedBuildingId() {
		return selectedBuildingId;
	}

	public void setSelectedBuildingId(long selectedBuildingId) {
		this.selectedBuildingId = selectedBuildingId;
	}

	public long getSelectedFloorId() {
		return selectedFloorId;
	}

	public void setSelectedFloorId(long selectedFloorId) {
		this.selectedFloorId = selectedFloorId;
	}

	public long getSelectedRoomId() {
		return selectedRoomId;
	}

	public void setSelectedRoomId(long selectedRoomId) {
		this.selectedRoomId = selectedRoomId;
	}

	public long getSelectedMachineId() {
		return selectedMachineId;
	}

	public void setSelectedMachineId(long selectedMachineId) {
		this.selectedMachineId = selectedMachineId;
	}

	public ScheduleControlService getScheduleControlService() {
		return scheduleControlService;
	}

	public void setScheduleControlService(ScheduleControlService scheduleControlService) {
		this.scheduleControlService = scheduleControlService;
	}

	public ScheduleTerm getEditItem() {
		return editItem;
	}

	public void setEditItem(ScheduleTerm editItem) {
		this.editItem = editItem;
	}


	public List<String> getClickedMachineId() {
		return clickedMachineId;
	}

	public void setClickedMachineId(List<String> clickedMachineId) {
		this.clickedMachineId = clickedMachineId;
	}

	public List<ScheduleTerm> getScheduleTerms() {
		return scheduleTerms;
	}

	public void setScheduleTerms(List<ScheduleTerm> scheduleTerms) {
		this.scheduleTerms = scheduleTerms;
	}

	public List<SelectItem> getClickedMachineOptions() {
		return clickedMachineOptions;
	}

	public void setClickedMachineOptions(List<SelectItem> clickedMachineOptions) {
		this.clickedMachineOptions = clickedMachineOptions;
	}

	public List<SelectItem> getHourOptions() {
		return hourOptions;
	}

	public void setHourOptions(List<SelectItem> hourOptions) {
		this.hourOptions = hourOptions;
	}

	public List<SelectItem> getMinuteOptions() {
		return minuteOptions;
	}

	public void setMinuteOptions(List<SelectItem> minuteOptions) {
		this.minuteOptions = minuteOptions;
	}

	public String getStatus() {
		return status;
	}

	public void setStatus(String status) {
		this.status = status;
	}

	public List<Machine> getSelectedMachines() {
		return selectedMachines;
	}

	public void setSelectedMachines(List<Machine> selectedMachines) {
		this.selectedMachines = selectedMachines;
	}

	public List<SelectItem> getMinimumTemperatureOptions() {
		return minimumTemperatureOptions;
	}

	public void setMinimumTemperatureOptions(List<SelectItem> minimumTemperatureOptions) {
		this.minimumTemperatureOptions = minimumTemperatureOptions;
	}

	public List<SelectItem> getTemperatureOptions() {
		return temperatureOptions;
	}

	public void setTemperatureOptions(List<SelectItem> temperatureOptions) {
		this.temperatureOptions = temperatureOptions;
	}

}
